import type {ExtendedFormApi} from '@/components/common/form';
import type {VxeGridInstance} from 'vxe-table';

import type {VxeGridProps} from './types';

import {toRaw} from 'vue';

import {Store} from '@/utils/shared/store';
import {
    bindMethods,
    isBoolean,
    isFunction,
    mergeWithArrayOverride,
    StateHandler,
} from '@/utils/shared/utils';

function getDefaultState(): VxeGridProps {
    return {
        class: '',
        gridClass: '',
        gridOptions: {},
        gridEvents: {},
        formOptions: undefined,
        showSearchForm: true,
    };
}

export class VxeGridApi {
    private isMounted = false;

    private stateHandler: StateHandler;
    public formApi = {} as ExtendedFormApi;

    // private prevState: null | VxeGridProps = null;
    public grid = {} as VxeGridInstance;

    public state: null | VxeGridProps = null;

    public store: Store<VxeGridProps>;

    constructor(options: VxeGridProps = {}) {
        const storeState = {...options};

        const defaultState = getDefaultState();
        this.store = new Store<VxeGridProps>(
            mergeWithArrayOverride(storeState, defaultState),
            {
                onUpdate: () => {
                    // this.prevState = this.state;
                    this.state = this.store.state;
                },
            },
        );

        this.state = this.store.state;
        this.stateHandler = new StateHandler();
        bindMethods(this);
    }

    mount(instance: null | VxeGridInstance, formApi: ExtendedFormApi) {
        if (!this.isMounted && instance) {
            this.grid = instance;
            this.formApi = formApi;
            this.stateHandler.setConditionTrue();
            this.isMounted = true;
        }
    }

    async query(params: Record<string, any> = {}) {
        try {
            await this.grid.commitProxy('query', toRaw(params));
        } catch (error) {
            console.error('Error occurred while querying:', error);
        }
    }

    async reload(params: Record<string, any> = {}) {
        try {
            await this.grid.commitProxy('reload', toRaw(params));
        } catch (error) {
            console.error('Error occurred while reloading:', error);
        }
    }

    setGridOptions(options: Partial<VxeGridProps['gridOptions']>) {
        this.setState({
            gridOptions: options,
        });
    }

    setLoading(isLoading: boolean) {
        this.setState({
            gridOptions: {
                loading: isLoading,
            },
        });
    }

    setState(
        stateOrFn:
            | ((prev: VxeGridProps) => Partial<VxeGridProps>)
            | Partial<VxeGridProps>,
    ) {
        if (isFunction(stateOrFn)) {
            this.store.setState((prev) => {
                return mergeWithArrayOverride(stateOrFn(prev), prev);
            });
        } else {
            this.store.setState((prev) => mergeWithArrayOverride(stateOrFn, prev));
        }
    }

    toggleSearchForm(show?: boolean) {
        this.setState({
            showSearchForm: isBoolean(show) ? show : !this.state?.showSearchForm,
        });
        // nextTick(() => {
        //   this.grid.recalculate();
        // });
        return this.state?.showSearchForm;
    }

    unmount() {
        this.isMounted = false;
        this.stateHandler.reset();
    }
}
